﻿Namespace MapObjects

    Public Class Player

        Private ModelObjects() As MapObjects.Models.ModelObject
        Private G As GraphicsDeviceManager
        Private ContentDir As String
        Public ModelRotation As Single = 0
        Private World As Matrix = Matrix.Identity
        Public SkyDomeColor1 As Vector4
        Public SkyDomeColor2 As Vector4
        Public ModelLocation As Vector3 = Vector3.Zero
        Public ModelVelocity As Vector3 = Vector3.Zero
        Private OldRotation As Single = 0
        Private OldLocation As Vector3 = Vector3.Zero
        Private OldVelocity As Vector3 = Vector3.Zero
        Private IsCharModel As Boolean

        Public Sub New(Graphics As GraphicsDeviceManager, ContentDirectory As String)
            G = Graphics
            ContentDir = ContentDirectory
        End Sub

        Public Sub ImportCOLLADAFile(FileName As String, Scale As Single)
            Dim ModMeshImporter As New Processors.ColladaMesh(G, ContentDir)
            ModMeshImporter.ImportDAEFile(FileName, Scale)
            ModelObjects = ModMeshImporter.GetModelObjects()
            SetModelParents()
            Call CompileModelsDAE()
        End Sub


        Private Sub SetModelParents()
            Dim i As Integer
            For i = 0 To ModelObjects.Count - 1
                Select Case ModelObjects(i).GroupName
                    Case "Stomach"
                        ModelObjects(i).ModelPartParent = 0
                        ModelObjects(i).ModelPartID = 1
                    Case "Upper_Body"
                        ModelObjects(i).ModelPartParent = 1
                        ModelObjects(i).ModelPartID = 2
                    Case "Left_Thigh"
                        ModelObjects(i).ModelPartParent = 1
                        ModelObjects(i).ModelPartID = 3
                    Case "Right_Thigh"
                        ModelObjects(i).ModelPartParent = 1
                        ModelObjects(i).ModelPartID = 4
                    Case "Left_Arm"
                        ModelObjects(i).ModelPartParent = 2
                        ModelObjects(i).ModelPartID = 5
                    Case "Right_Arm"
                        ModelObjects(i).ModelPartParent = 2
                        ModelObjects(i).ModelPartID = 6
                    Case "Neck"
                        ModelObjects(i).ModelPartParent = 2
                        ModelObjects(i).ModelPartID = 7
                    Case "Head"
                        ModelObjects(i).ModelPartParent = 7
                        ModelObjects(i).ModelPartID = 8
                    Case "Nose"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 9
                    Case "Left_Ear"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 10
                    Case "Left_Eye"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 11
                    Case "Horns"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 12
                    Case "Right_Ear"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 13
                    Case "Right_Eye"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 14
                    Case "Mouth"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 15
                    Case "EyeBalls"
                        ModelObjects(i).ModelPartParent = 8
                        ModelObjects(i).ModelPartID = 16
                    Case "Left__Forearm"
                        ModelObjects(i).ModelPartParent = 5
                        ModelObjects(i).ModelPartID = 17
                    Case "Right_Forearm"
                        ModelObjects(i).ModelPartParent = 6
                        ModelObjects(i).ModelPartID = 18
                    Case "Left_Hand"
                        ModelObjects(i).ModelPartParent = 17
                        ModelObjects(i).ModelPartID = 19
                    Case "Right_Hand"
                        ModelObjects(i).ModelPartParent = 18
                        ModelObjects(i).ModelPartID = 20
                    Case "Left_Leg"
                        ModelObjects(i).ModelPartParent = 3
                        ModelObjects(i).ModelPartID = 21
                    Case "Right_Leg"
                        ModelObjects(i).ModelPartParent = 4
                        ModelObjects(i).ModelPartID = 22
                    Case "Left_Foot"
                        ModelObjects(i).ModelPartParent = 21
                        ModelObjects(i).ModelPartID = 23
                    Case "Right_Foot"
                        ModelObjects(i).ModelPartParent = 22
                        ModelObjects(i).ModelPartID = 24
                End Select
            Next i
        End Sub

        Public Sub Update(TimeDiff As Single, KeyState As KeyboardState)
            Dim i As Integer
            If IsCharModel = True Then
                'If KeyState.IsKeyDown(Keys.A) Then
                'ModelRotation = ModelRotation + TimeDiff
                'CopyTransforms(0, ModelRotation * 0.5)
                'SetModelRotation(1, ModelRotation)
                'ElseIf KeyState.IsKeyDown(Keys.D) Then
                'ModelRotation = ModelRotation - TimeDiff
                'CopyTransforms(0, ModelRotation * 0.5)
                'SetModelRotation(1, ModelRotation)
                If KeyState.IsKeyDown(Keys.W) Then
                    'ApplyTranslation(TimeDiff, 1, KeyState.IsKeyDown(Keys.LeftShift))
                ElseIf KeyState.IsKeyDown(Keys.A) Then
                    'ApplyTranslation(TimeDiff, 2, False)
                ElseIf KeyState.IsKeyDown(Keys.D) Then
                    'ApplyTranslation(TimeDiff, 3, False)
                ElseIf KeyState.IsKeyDown(Keys.S) Then
                    'ApplyTranslation(TimeDiff, 0, True)
                ElseIf KeyState.IsKeyDown(Keys.None) Then
                    ModelVelocity = Vector3.Zero
                End If
                If OldLocation <> ModelLocation Or OldRotation <> ModelRotation Or OldVelocity <> ModelVelocity Then
                    For i = 0 To ModelObjects.Count - 1
                        RepositionVerts(ModelObjects(i))
                    Next i
                    World = Matrix.CreateFromAxisAngle(Vector3.UnitY, ModelRotation) * Matrix.CreateTranslation(ModelLocation)
                    OldLocation = ModelLocation
                    OldVelocity = ModelVelocity
                    OldRotation = ModelRotation
                End If
            End If
        End Sub

        Private Sub RepositionVerts(ByRef MO As MapObjects.Models.ModelObject)
            Dim i As Integer
            Dim VT As New List(Of VertexPositionNormalTexture)
            Dim tmp As VertexPositionNormalTexture
            For i = 0 To MO.ModelVertices.Count - 1
                tmp = MO.ModelVertices(i)
                tmp.Position = MO.ModelVertices(i).Position + ModelVelocity
                VT.Add(tmp)
            Next i
            MO.ModelVertices = VT
            MO.VertexBuffer = New VertexBuffer(G.GraphicsDevice, VertexPositionNormalTexture.VertexDeclaration, VT.Count, BufferUsage.WriteOnly)
            MO.VertexBuffer.SetData(Of VertexPositionNormalTexture)(VT.ToArray)
        End Sub

        Public Sub InitializePlayer()
            Dim i As Integer
            For i = 0 To ModelObjects.Count - 1
                ModelObjects(i).WorldMatrix = Matrix.Identity
                RepositionVerts(ModelObjects(i))
            Next i
        End Sub

        Private Sub CompileModelsDAE()
            Dim i As Integer, j As Integer
            Dim ID() As MapObjects.Models.IndexData
            'Dim NewID() As Integer
            Dim Verts As List(Of VertexPositionNormalTexture)
            Dim IndList As List(Of Integer)
            Dim V() As Vector3
            Dim TC() As Vector2
            Dim N() As Vector3
            Dim VT As VertexPositionNormalTexture
            For i = 0 To ModelObjects.Count - 1
                ReDim V(ModelObjects(i).Positions.Count - 1)
                For j = 0 To ModelObjects(i).Positions.Count - 1
                    V(j) = ModelObjects(i).Positions(j) + ModelLocation
                Next j
                ReDim TC(ModelObjects(i).TexCoords.Count - 1)
                For j = 0 To ModelObjects(i).TexCoords.Count - 1
                    TC(j) = ModelObjects(i).TexCoords(j)
                Next j
                ReDim N(ModelObjects(i).Normals.Count - 1)
                For j = 0 To ModelObjects(i).Normals.Count - 1
                    N(j) = ModelObjects(i).Normals(j)
                Next j
                ReDim ID(ModelObjects(i).Indices.Count - 1)
                For j = 0 To ModelObjects(i).Indices.Count - 1
                    ID(j) = ModelObjects(i).Indices(j)
                Next j

                IndList = New List(Of Integer)
                Verts = New List(Of VertexPositionNormalTexture)
                For j = 0 To ID.Count - 3 Step 3
                    VT.Position = V(ID(j + 2).Vertex)
                    If ID(j + 2).Normal = -999 Then
                        VT.Normal = Vector3.Zero
                    Else
                        VT.Normal = N(ID(j + 2).Normal)
                    End If
                    If ID(j + 2).TextCoord = -999 Then
                        VT.TextureCoordinate = Vector2.Zero
                    Else
                        VT.TextureCoordinate = TC(ID(j + 2).TextCoord)
                    End If
                    Verts.Add(VT)
                    IndList.Add(j)

                    VT.Position = V(ID(j + 1).Vertex)
                    If ID(j + 1).Normal = -999 Then
                        VT.Normal = Vector3.Zero
                    Else
                        VT.Normal = N(ID(j + 1).Normal)
                    End If
                    If ID(j + 1).TextCoord = -999 Then
                        VT.TextureCoordinate = Vector2.Zero
                    Else
                        VT.TextureCoordinate = TC(ID(j + 1).TextCoord)
                    End If
                    Verts.Add(VT)
                    IndList.Add(j + 1)

                    VT.Position = V(ID(j + 0).Vertex)
                    If ID(j + 0).Normal = -999 Then
                        VT.Normal = Vector3.Zero
                    Else
                        VT.Normal = N(ID(j + 0).Normal)
                    End If
                    If ID(j + 0).TextCoord = -999 Then
                        VT.TextureCoordinate = Vector2.Zero
                    Else
                        VT.TextureCoordinate = TC(ID(j + 0).TextCoord)
                    End If
                    Verts.Add(VT)
                    IndList.Add(j + 2)


                Next j
                ModelObjects(i).ModelVertices = Verts
                ModelObjects(i).ModelIndices = IndList
                ModelObjects(i).VertexBuffer = New VertexBuffer(G.GraphicsDevice, VertexPositionNormalTexture.VertexDeclaration, Verts.Count, BufferUsage.WriteOnly)
                ModelObjects(i).VertexBuffer.SetData(Of VertexPositionNormalTexture)(Verts.ToArray)
                ModelObjects(i).IndexBuffer = New IndexBuffer(G.GraphicsDevice, IndexElementSize.ThirtyTwoBits, IndList.Count, BufferUsage.WriteOnly)
                ModelObjects(i).IndexBuffer.SetData(IndList.ToArray)
            Next i
        End Sub

        Public Sub Draw(Device As GraphicsDevice, Effect As Effect, Camera As Cameras.FirstPerson, LightDirection As Vector3, LightAmbientValue As Single, Optional IsSkyDome As Boolean = False, Optional IsReflection As Boolean = False, Optional WaterOffset As Single = 0)
            Dim i As Integer, VB As VertexBuffer, IB As IndexBuffer
            For i = 0 To ModelObjects.Count - 1
                If IsSkyDome = True Then
                    Effect.CurrentTechnique = Effect.Techniques("SkyDome")
                    Effect.Parameters("xSkyTopColor").SetValue(SkyDomeColor1)
                    Effect.Parameters("xSkyBottomColor").SetValue(SkyDomeColor2)
                Else
                    Effect.CurrentTechnique = Effect.Techniques("Textured")
                End If
                Effect.Parameters("xWorld").SetValue(World * ModelObjects(i).WorldMatrix)
                If IsReflection = True Then
                    Effect.Parameters("xView").SetValue(Camera.GetReflectionViewMatrix(WaterOffset))
                Else
                    Effect.Parameters("xView").SetValue(Camera.GetViewMatrix)
                End If
                Effect.Parameters("xProjection").SetValue(Camera.GetProjMatrix)
                Effect.Parameters("xEnableLighting").SetValue(True)
                Effect.Parameters("xLightDirection").SetValue(LightDirection)
                Effect.Parameters("xAmbient").SetValue(LightAmbientValue)
                Effect.Parameters("xTexture").SetValue(ModelObjects(i).ModelTexture)
                For Each pass In Effect.CurrentTechnique.Passes
                    pass.Apply()
                    VB = New VertexBuffer(G.GraphicsDevice, VertexPositionNormalTexture.VertexDeclaration, ModelObjects(i).ModelVertices.Count, BufferUsage.WriteOnly)
                    VB.SetData(ModelObjects(i).ModelVertices.ToArray)
                    Device.SetVertexBuffer(VB)
                    IB = New IndexBuffer(G.GraphicsDevice, IndexElementSize.ThirtyTwoBits, ModelObjects(i).ModelIndices.Count, BufferUsage.WriteOnly)
                    IB.SetData(ModelObjects(i).ModelIndices.ToArray)
                    Device.Indices = IB
                    Device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, ModelObjects(i).ModelIndices.Count, 0, CInt(ModelObjects(i).ModelIndices.Count / 3))
                    'Device.SetVertexBuffer(Nothing)
                    'Device.Indices = Nothing
                Next
            Next i
        End Sub

    End Class

End Namespace